package cn.edu.zisu.common.util;

import org.apache.commons.collections4.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class LambdaTranslator {
    public static <K, T> Map<K, List<T>> groupByKey(Collection<T> collection, Function<? super T, ? extends K> keyMapper) {
        if (CollectionUtils.isEmpty(collection)) {
            return Collections.emptyMap();
        }
        return collection.stream().collect(Collectors.groupingBy(keyMapper));
    }

    public static <K, T> Map<K, T> getKeyObjectMap(Collection<T> collection, Function<? super T, ? extends K> keyMapper) {
        if (CollectionUtils.isEmpty(collection)) {
            return Collections.emptyMap();
        }
        Function<T, T> valMapper = Function.identity();
        return collection.stream().collect(Collectors.toMap(keyMapper, valMapper, (a, b) -> b));
    }

    public static <T, R> List<R> getFilterList(Collection<T> collection, Predicate<? super T> filter, Function<? super T, ? extends R> mapper) {
        if (CollectionUtils.isEmpty(collection)) {
            return Collections.emptyList();
        }
        return collection.stream().filter(filter).map(mapper).distinct().collect(Collectors.toList());
    }

    public static <K, T> Set<K> getKeysFromCollection(Collection<T> collection, Function<? super T, ? extends K> keyMapper) {
        if (CollectionUtils.isEmpty(collection)) {
            return Collections.emptySet();
        }
        return collection.stream().filter(Objects::nonNull).map(keyMapper).collect(Collectors.toSet());
    }

    public static <T> Stream<T> asStream(Iterator<T> sourceIterator) {
        return asStream(sourceIterator, false);
    }

    public static <T> Stream<T> asStream(Iterator<T> sourceIterator, boolean parallel) {
        Iterable<T> iterable = () -> sourceIterator;
        return StreamSupport.stream(iterable.spliterator(), parallel);
    }

}
